/*
* Copyright (c)  2017, ueboot.com
* All rights reserved.
* 2017-10-14 21:28:34
*/
package com.ueboot.weishop.service.goods.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.ueboot.weishop.entity.activity.ActivityEntity;
import com.ueboot.weishop.entity.goods.*;
import com.ueboot.core.repository.BaseRepository;
import com.ueboot.weishop.entity.setting.BrandEntity;
import com.ueboot.weishop.entity.setting.CategoryEntity;
import com.ueboot.weishop.repository.goods.GoodsInfoRepository;
import com.ueboot.core.service.impl.BaseServiceImpl;
import com.ueboot.weishop.repository.setting.CategoryRepository;
import com.ueboot.weishop.service.activity.ActivityService;
import com.ueboot.weishop.service.goods.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yangkui  on 2017-10-14 21:28:34.
 *
 * @author yangkui
 * @since 2.0 by autocode
 */
@Slf4j
@Service
public class GoodsInfoServiceImpl extends BaseServiceImpl<GoodsInfoEntity> implements GoodsInfoService {
	@Autowired
	private GoodsInfoRepository goodsInfoRepository;

	@Autowired
	private GoodsSpecService goodsSpecService;

	@Autowired
	private GoodsSpecValueService goodsSpecValueService;

	@Autowired
	private GoodsAttrService goodsAttrService;

	@Autowired
	private GoodsSalesSpecService goodsSalesSpecService;

	@Autowired
	private CategoryRepository categoryRepository;

	@Autowired
	private ActivityService activityService;

	@Override
	protected BaseRepository getBaseRepository() {
		return goodsInfoRepository;
	}


	@Override
	public Page<GoodsInfoEntity> findByActivity(Pageable pageable, String activityId) {
		return goodsInfoRepository.findByActivityFullPathIds(pageable, activityId);
	}

	@Override
	@CacheEvict(allEntries = true, cacheNames = "goodsInfo")
	@Transactional(rollbackFor = Exception.class, timeout = 120, propagation = Propagation.REQUIRED)
	public void delete(Long[] ids) {
		super.delete(ids);
		//删除其他关联信息
		for (Long id : ids) {
			goodsSalesSpecService.deleteGoodsSalesSpecEntitiesByGoodsInfoId(id);
			goodsSpecService.deleteGoodsSpecEntitiesByGoodsInfoId(id);
			goodsSpecValueService.deleteGoodsSpecValueEntitiesByGoodsInfoId(id);
			goodsAttrService.deleteGoodsAttrEntitiesByGoodsInfoId(id);
		}
	}

	@Override
	@CacheEvict(allEntries = true, cacheNames = "goodsInfo")
	public GoodsInfoEntity save(GoodsInfoEntity object) {
		return super.save(object);
	}

	/**
	 * 根据ID查找商品对象的json格式字符串，用于存放到缓存当中。
	 *
	 * @param goodsInfoId 商品ID
	 * @return
	 */
	@Override
	@Cacheable(key = "'weishop:goodsInfoJsonById:'+#goodsInfoId", cacheNames = "goodsInfo")
	public String findById(Long goodsInfoId) {
		GoodsInfoEntity entity = super.get(goodsInfoId);
		if (entity == null) {
			return null;
		}
		return toJson(entity);
	}

	@Override
	public void deleteGoodsFree(List<Integer> ids) {
		List<GoodsInfoEntity> goodsInfoEntityList = Lists.newLinkedList();
		for (Integer id : ids) {
			GoodsInfoEntity entity = goodsInfoRepository.getOne(Long.valueOf(id));
			entity.setActivity(null);
			entity.setActivityFullPathIds(null);
			entity.setActivityFullPathName(null);
			goodsInfoEntityList.add(entity);
		}
		goodsInfoRepository.save(goodsInfoEntityList);
	}

	private String toJson(GoodsInfoEntity entity) {
		//防止存放缓存时导致json转换异常，先进行一次加载
		if(entity.getActivity()!=null){
			ActivityEntity activityEntity = activityService.findById(entity.getActivity().getId());
			entity.setActivity(activityEntity);
		}
		BrandEntity brandEntity = entity.getBrand();
		if (brandEntity != null) {
			brandEntity.setCategory(null);
		}
		CategoryEntity categoryEntity = entity.getCategory();
		categoryEntity.setParent(null);
		return JSON.toJSONString(entity);
	}

	/**
	 * 级联保存商品信息和商品关联的规格、属性、价格等信息
	 *
	 * @param goodsInfoEntity        商品本身基础信息
	 * @param goodsSpecValueEntities 规格值列表
	 * @param goodsAttrEntities      属性列表
	 * @param goodsSalesSpecEntities 价格列表
	 */
	@Override
	@Transactional(rollbackFor = Exception.class, timeout = 120, propagation = Propagation.REQUIRED)
	@CacheEvict(allEntries = true, cacheNames = "goodsInfo")
	public void saveGoodsInfo(GoodsInfoEntity goodsInfoEntity, List<GoodsSpecValueEntity> goodsSpecValueEntities,
	                          List<GoodsAttrEntity> goodsAttrEntities, List<GoodsSalesSpecEntity> goodsSalesSpecEntities) {
		log.info("开始保存商品信息，标题:{}", goodsInfoEntity.getName());
		//1.先保存商品基本信息
		this.save(goodsInfoEntity);
		//2.从规格值列表当中，找到所有需要保存的规格，进行保存，再保存规格值
		goodsSpecValueEntities.forEach((entity) -> {
			goodsSpecService.save(entity.getGoodsSpec());
			goodsSpecValueService.save(entity);
		});
		//3.保持属性列表
		goodsAttrEntities.forEach((entity) -> {
			goodsAttrService.save(entity);
		});

		//4.保存价格列表
		goodsSalesSpecEntities.forEach((entity) -> {
			goodsSalesSpecService.save(entity);
		});
		log.info("保存商品信息成功。ID:{}", goodsInfoEntity.getId());
	}

	/**
	 * 清空缓存
	 */
	@Override
	@CacheEvict(allEntries = true, cacheNames = "goodsInfo")
	public void clearGoodsInfoCache() {
		log.info("清空goodsInfo缓存");
	}

	/**
	 * 根据活动ID，查找活动对应的商品
	 *
	 * @param activityId
	 * @return
	 */
	@Override
	public List<GoodsInfoEntity> findByActivityId(Long activityId) {
		return goodsInfoRepository.findByActivityId(activityId);
	}

	/**
	 * 根据活动ID，查找活动对应的商品，返回的格式为对象的json字符串，需要自己转一下
	 * 结果进行了缓存
	 *
	 * @param activityId
	 * @return
	 */
	@Override
	public List<String> findJSONByActivityId(Long activityId) {
		List<GoodsInfoEntity> list = this.findByActivityId(activityId);
		List<String> jsons = new ArrayList<>();
		for (GoodsInfoEntity g : list) {
			jsons.add(toJson(g));
		}
		return jsons;
	}

	/**
	 * 根据分类ID，查找分类对应的商品
	 *
	 * @param categoryId
	 * @return
	 */
	@Override
	@Cacheable(key = "'weishop:goodsInfoByCategory:'+#categoryId", cacheNames = "goodsInfo")
	public List<GoodsInfoEntity> findByCategoryId(Long categoryId) {
		return goodsInfoRepository.findByCategoryId(categoryId);
	}

	@Override
	@Cacheable(key = "'weishop:goodsInfoByCategory:'+#code", cacheNames = "goodsInfo")
	public List<GoodsInfoEntity> findByCode(String code) {
		CategoryEntity categoryEntity = categoryRepository.findByCode(code);
		if (categoryEntity == null) {
			return new ArrayList<>();
		}
		return goodsInfoRepository.findByCategoryId(categoryEntity.getId());
	}
}
